package com.sunda.spmsoversea.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmscommon.feign.IFeignServiceCommon;
import com.sunda.spmsoversea.dto.OverseaWhsDumpDTO;
import com.sunda.spmsoversea.dto.OverseaWhsDumpQueryDTO;
import com.sunda.spmsoversea.entity.OverseaWhsDump;
import com.sunda.spmsoversea.entity.OverseaWhsDumpDtl;
import com.sunda.spmsoversea.entity.WhsStorageInventory;
import com.sunda.spmsoversea.mapper.OverseaWhsDumpMapper;
import com.sunda.spmsoversea.service.*;
import com.sunda.spmsuser.entity.SpmsUser;
import feign.FeignException;
import localhost.services.RequestService.RequestServicePortTypeProxy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import weaver.soa.workflow.request.MainTableInfo;
import weaver.soa.workflow.request.Property;
import weaver.soa.workflow.request.RequestInfo;

import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.sunda.spmscommon.constant.OaConstant.BUSINESS_TYPE_OVERSEA_DUMP;
import static com.sunda.spmsoversea.constant.CommonConstant.*;
import static com.sunda.spmsoversea.constant.SapConstant.SAP_SUCCESS;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.*;
import static com.sunda.spmsoversea.enums.OverseaWhsDumpEnum.*;

/**
 * <p>
 * 海外仓转储任务表 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-11-02
 */
@Service
@Slf4j
public class OverseaWhsDumpServiceImpl extends ServiceImpl<OverseaWhsDumpMapper, OverseaWhsDump> implements IOverseaWhsDumpService {

    @Autowired
    IOverseaWhsDumpDtlService iOverseaWhsDumpDtlService;

    @Autowired
    IOverseaOperateLogService iOverseaOperateLogService;

    @Autowired
    IWhsStorageInventoryService iWhsStorageInventoryService;

    @Autowired
    IWhsOperateLogService iWhsOperateLogService;

    @Autowired
    IFeignServiceCommon iFeignServiceCommon;

    @Autowired
    IFormatDataToSapService iFormatDataToSapService;

    @Value("${oa.workflow.id0733}")
    String workflow0733;

    @Override
    public ResponseResult getWhsDumpPage(OverseaWhsDumpQueryDTO overseaWhsDumpQueryDTO) {
        IPage<Map<String, Object>> iPage = overseaWhsDumpQueryDTO.getPage();
        iPage.setRecords(this.baseMapper.getWhsDumpPage(iPage, overseaWhsDumpQueryDTO));
        return ResponseResult.success().add("overseaWhsDumpList", iPage);
    }

    public OverseaWhsDump getOverseaWhsDump(String whsDumpUuid){
        QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        return this.baseMapper.selectOne(queryWrapper);
    }

    @Override
    public List<Map<String, Object>> getWhsDumpDtls(String whsDumpUuid) {
        return iOverseaWhsDumpDtlService.getWhsDumpDtlList(whsDumpUuid);
    }

    /**
     海外SPMS转储单据状态:0删除；1草稿；2待审批；3SPMS审批通过(提交OA);4OA驳回(操作同1);5OA审批通过(出库中);6出库完成;
     7提交SAP获取PO失败;8提交SAP获取PO;9提交SAP获取DN失败;10提交SAP获取DN成功(扣转出方库存);11转出已撤销(撤到状态5出库中，SAP撤回成功则加回库存);
     新建固定值：采购组240，采购组织1000，凭证类型传值公司内ZU01，公司间ZC01；
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult createWhsDump(OverseaWhsDumpDTO overseaWhsDumpDTO, String userId, SpmsUser spmsUser) {
        try {
            ResponseResult checkResult = checkCreate(overseaWhsDumpDTO);
            if (checkResult.getCode() != SUCCESS){
                return checkResult;
            }
            String whsDumpUuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
            String spmsStatus = overseaWhsDumpDTO.getSpmsStatus();
            QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
            /** 创建转储任务日志 */
            iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_CANCEL_CREATE.getDescZh(), WHS_DUMP_CANCEL_CREATE.getDescEn(), "");

            /** 创建转储任务表头 */
            int createDumpResult = createOverseaWhsDump(whsDumpUuid, overseaWhsDumpDTO, userId);
            if (createDumpResult < 1){
                log.info("=======RuntimeException=========创建转储任务表头错误\n");
                throw new RuntimeException("创建转储任务表头错误");
            }

            /** 创建转储任务明细 */
            int createDumpDtlResult = createOverseaWhsDumpDtl(whsDumpUuid, overseaWhsDumpDTO);
            if (createDumpDtlResult < 1){
                log.info("=======RuntimeException=========创建转储任务行项目错误\n");
                throw new RuntimeException("创建转储任务行项目错误");
            }

            /** spmsStatus = 3 时创建转储任务申请直接提交OA，返回结果 > 0 表示提交成功的OA单据号 */
            if (WHS_DUMP_SUBMIT_OA.getCode().equals(spmsStatus)){
                int oaBianhao = whsDumpSubmitOa(whsDumpUuid, overseaWhsDumpDTO.getSubmitOaDate(), spmsUser);
                OverseaWhsDump overseaWhsDump = getOverseaWhsDump(whsDumpUuid);
                if (oaBianhao > 0){
                    //iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_SUBMIT_OA.getDescZh(), WHS_DUMP_SUBMIT_OA.getDescEn(), "");
                    overseaWhsDump.setOaWorkflow("0733");
                    overseaWhsDump.setSpmsStatus(WHS_DUMP_SUBMIT_OA.getCode());
                    overseaWhsDump.setSubmitOaDate(overseaWhsDumpDTO.getSubmitOaDate());
                    overseaWhsDump.setOaBianhao(String.valueOf(oaBianhao));
                    this.baseMapper.update(overseaWhsDump, queryWrapper);

                    return ResponseResult.success("转储任务提交OA成功")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid))
                            .add("oaBianhao", oaBianhao);
                } else {
                    //iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_SUBMIT_OA_ERROR.getDescZh(), WHS_DUMP_SUBMIT_OA_ERROR.getDescEn(), "");
                    overseaWhsDump.setOaWorkflow("0733");
                    overseaWhsDump.setSpmsStatus(WHS_DUMP_SAVE.getCode());
                    overseaWhsDump.setSubmitOaDate(overseaWhsDumpDTO.getSubmitOaDate());
                    this.baseMapper.update(overseaWhsDump, queryWrapper);
                    return ResponseResult.error("转储任务创建成功，提交OA失败")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid))
                            .add("oaBianhao", oaBianhao);
                }
            } else {
                return ResponseResult.success("转储任务创建成功")
                        .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                        .add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid));
            }
        }catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("请求执行过程出错请重试").add("error", e.getMessage());
        }
    }

    int createOverseaWhsDump(String whsDumpUuid, OverseaWhsDumpDTO overseaWhsDumpDTO, String userId){
        OverseaWhsDump overseaWhsDump = new OverseaWhsDump();
        overseaWhsDump.setWhsDumpUuid(whsDumpUuid);
        overseaWhsDump.setWerksDumpIn(overseaWhsDumpDTO.getWerksDumpIn());
        overseaWhsDump.setWhsLocationCodeDumpIn(overseaWhsDumpDTO.getWhsLocationCodeDumpIn());
        overseaWhsDump.setWerksDumpOut(overseaWhsDumpDTO.getWerksDumpOut());
        overseaWhsDump.setWhsLocationCodeDumpOut(overseaWhsDumpDTO.getWhsLocationCodeDumpOut());
        overseaWhsDump.setCreateDate(overseaWhsDumpDTO.getCreateDate());
        overseaWhsDump.setSpmsStatus(WHS_DUMP_SAVE.getCode());
        overseaWhsDump.setOaRemark(overseaWhsDumpDTO.getOaRemark());
        overseaWhsDump.setDeliveryDate(overseaWhsDumpDTO.getDeliveryDate());
        overseaWhsDump.setVoucherType(overseaWhsDumpDTO.getVoucherType());
        overseaWhsDump.setPurchaseGroup(overseaWhsDumpDTO.getPurchaseGroup());
        overseaWhsDump.setPurchaseOrg(overseaWhsDumpDTO.getPurchaseOrg());
        overseaWhsDump.setCreateUserid(userId);
        return this.baseMapper.insert(overseaWhsDump);
    }

    int createOverseaWhsDumpDtl(String whsDumpUuid, OverseaWhsDumpDTO overseaWhsDumpDTO){
        List<OverseaWhsDumpDtl> dtlList = overseaWhsDumpDTO.getOverseaWhsDumpDtlList();
        int createResult = 0;
        for (int i = 0; i < dtlList.size(); i ++){
            OverseaWhsDumpDtl dtl = dtlList.get(i);
            OverseaWhsDumpDtl overseaWhsDumpDtl = new OverseaWhsDumpDtl();
            overseaWhsDumpDtl.setWhsDumpUuid(whsDumpUuid);
            overseaWhsDumpDtl.setItem((i + 1) * 10);
            overseaWhsDumpDtl.setMaterialNo(dtl.getMaterialNo());
            overseaWhsDumpDtl.setBasicUnit(dtl.getBasicUnit());
            overseaWhsDumpDtl.setUnitSales(dtl.getUnitSales());
            overseaWhsDumpDtl.setApplyQtyBasicUnit(dtl.getApplyQtyBasicUnit() == null ? 0.0 : dtl.getApplyQtyBasicUnit());
            overseaWhsDumpDtl.setApplyQtyUnitSales(dtl.getApplyQtyUnitSales() == null ? 0.0 : dtl.getApplyQtyUnitSales());
            overseaWhsDumpDtl.setApplyRemark(dtl.getApplyRemark());
            overseaWhsDumpDtl.setActualQtyBasicUnit(0.0);
            overseaWhsDumpDtl.setActualQtyUnitSales(0.0);
            if (iOverseaWhsDumpDtlService.save(overseaWhsDumpDtl)){
                createResult += 1;
            }
        }
        return createResult;
    }

    int whsDumpSubmitOa(String whsDumpUuid, String submitOaDate, SpmsUser spmsUser){
        QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);
        String spmsStatus = overseaWhsDump.getSpmsStatus();

        RequestServicePortTypeProxy wfproxy = new RequestServicePortTypeProxy();
        try {
            RequestInfo reqinfo = new RequestInfo();
            reqinfo.setCreatorid(spmsUser.getWorkId()); // OAID 提交人
            reqinfo.setWorkflowid(workflow0733);// workflowid 为测试系统ID
            reqinfo.setRequestlevel("0");// 紧急程度 默认
            reqinfo.setRemindtype("0"); // 默认
            reqinfo.setIsNextFlow("1"); // 默认
            reqinfo.setDescription("海外仓转储申请单号" + overseaWhsDump.getWhsDumpNo() + "审批"); // 自定义

            Map<String, Object> mapHead = new HashMap<>();
            mapHead.put("sdnumber", "");
            mapHead.put("sdworkcode", spmsUser.getUserId());
            mapHead.put("sddate", submitOaDate);
            mapHead.put("sdapplicant", spmsUser.getWorkId());
            mapHead.put("sddepartment", spmsUser.getDeptId() == null  ? "" : spmsUser.getDeptId());
            mapHead.put("sdjobtitle", spmsUser.getPositionId() == null  ? "" : spmsUser.getPositionId());
            mapHead.put("sdsub", spmsUser.getCompany() == null ? "" : spmsUser.getCompany());
            mapHead.put("sdpoint", spmsUser.getBranchPoint() == null ? "" : spmsUser.getBranchPoint());
            mapHead.put("sdline", spmsUser.getBranchLine() == null ? "" : spmsUser.getBranchLine());
            mapHead.put("sdexplain", "");
            mapHead.put("sddumptasklistno", overseaWhsDump.getWhsDumpNo());
            mapHead.put("sdInfactory", overseaWhsDump.getWerksDumpIn());
            mapHead.put("sdexfactory", overseaWhsDump.getWerksDumpOut());
            mapHead.put("sdinwarehouse", overseaWhsDump.getWhsLocationCodeDumpIn());
            mapHead.put("sdexwarehouse", overseaWhsDump.getWhsLocationCodeDumpOut());
            mapHead.put("sdseason", overseaWhsDump.getOaRemark() == null ? "" : overseaWhsDump.getOaRemark());
            mapHead.put("sdneeddate", overseaWhsDump.getDeliveryDate());
            mapHead.put("sdexremark", overseaWhsDump.getDumpOutRemark() == null ? "" : overseaWhsDump.getDumpOutRemark());
            mapHead.put("spmsordernum", overseaWhsDump.getWhsDumpNo());
            mapHead.put("businessType", BUSINESS_TYPE_OVERSEA_DUMP);

            MainTableInfo wmi = new MainTableInfo();
            Property[] wrti = new Property[mapHead.size()];
            int i = 0;
            for (Map.Entry<String, Object> entry : mapHead.entrySet()){
                wrti[i] = new Property();
                wrti[i].setName(entry.getKey());
                wrti[i].setValue(entry.getValue() == null ? "" : entry.getValue().toString());
                i ++;
            }
            wmi.setProperty(wrti);
            reqinfo.setMainTableInfo(wmi);
            log.info("==========海外转储申请提交OA reqinfo==========\n" + JSON.toJSONString(reqinfo));

            int reqid = Integer.parseInt(wfproxy.createRequest(reqinfo));

            log.info("==========海外转储申请提交OA审批，返回 reqid:" + reqid);
            if (reqid > 0){
                iOverseaOperateLogService.addOverseaOperateLog(spmsUser.getUserId(), whsDumpUuid, WHS_DUMP_SUBMIT_OA.getDescZh()  + ":" + String.valueOf(reqid),
                        WHS_DUMP_SUBMIT_OA.getDescEn(), oaLog, JSON.toJSONString(reqinfo), String.valueOf(reqid), "");
            } else {
                iOverseaOperateLogService.addOverseaOperateLog(spmsUser.getUserId(), whsDumpUuid, WHS_DUMP_SUBMIT_OA_ERROR.getDescZh() + ":" + String.valueOf(reqid),
                        WHS_DUMP_SUBMIT_OA_ERROR.getDescEn(), oaLog, JSON.toJSONString(reqinfo), String.valueOf(reqid), "");
            }
            return reqid;
        }catch (RemoteException remoteException){
            remoteException.printStackTrace();
            log.info("=========海外转储申请提交OA连接错误=========" + remoteException.getMessage());
            return 0;
        } catch (Exception e){
            e.printStackTrace();
            log.error("========海外转储申请提交OA请求参数：" + whsDumpUuid + "\n请求提交OA异常=========\n" + e.getMessage());
            return 0;
        }
    }

    ResponseResult checkCreate(OverseaWhsDumpDTO overseaWhsDumpDTO){
        if (overseaWhsDumpDTO == null){
            return ResponseResult.error("请求参数错误");
        }
        if (StringUtils.isEmpty(overseaWhsDumpDTO.getWerksDumpIn()) || StringUtils.isEmpty(overseaWhsDumpDTO.getWhsLocationCodeDumpIn())
                || StringUtils.isEmpty(overseaWhsDumpDTO.getWerksDumpOut()) || StringUtils.isEmpty(overseaWhsDumpDTO.getWhsLocationCodeDumpOut())
                || StringUtils.isEmpty(overseaWhsDumpDTO.getCreateDate()) || StringUtils.isEmpty(overseaWhsDumpDTO.getSpmsStatus())
                || StringUtils.isEmpty(overseaWhsDumpDTO.getDeliveryDate())){
            return ResponseResult.error("请求参数错误");
        }
        String spmsStatus = overseaWhsDumpDTO.getSpmsStatus();
        if (WHS_DUMP_SUBMIT_OA.getCode().equals(spmsStatus) && StringUtils.isEmpty(overseaWhsDumpDTO.getSubmitOaDate())){
            return ResponseResult.error("请求参数错误");
        }
        List<OverseaWhsDumpDtl> overseaWhsDumpDtlList = overseaWhsDumpDTO.getOverseaWhsDumpDtlList();
        if (overseaWhsDumpDtlList == null || overseaWhsDumpDtlList.size() == 0){
            return ResponseResult.error("请求参数任务明细行数据不能为空");
        }
        return ResponseResult.success();
    }

    /** 转储任务关闭，状态变化为：1-0,4-0,5-0 */
    @Override
    public synchronized ResponseResult closeWhsDump(String whsDumpUuid, Integer dataVersion, String userId) {
        if (StringUtils.isEmpty(whsDumpUuid) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);
        if (overseaWhsDump == null){
            return ResponseResult.error("请求转储任务不存在");
        }
        if (!dataVersion.equals(overseaWhsDump.getDataVersion())){
            return ResponseResult.error("请求转储任务已更新请刷新后重试");
        }
        String spmsStatus = overseaWhsDump.getSpmsStatus();
        if (!WHS_DUMP_SAVE.getCode().equals(spmsStatus)
                && !WHS_DUMP_OA_REJECT.getCode().equals(spmsStatus)
                && !WHS_DUMP_OA_APPROVE.getCode().equals(spmsStatus)){
            return ResponseResult.error("转储任务当前状态禁止此操作");
        }
        overseaWhsDump.setSpmsStatus(WHS_DUMP_DELETE.getCode());
        this.baseMapper.update(overseaWhsDump, queryWrapper);
        iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_DELETE.getDescZh(), WHS_DUMP_DELETE.getDescEn(), "");
        return ResponseResult.success("转储任务已删除");
    }

    /** 转储任务新增行项目 */
    @Override
    public synchronized ResponseResult addOverseaWhsDumpDtls(List<OverseaWhsDumpDtl> dumpDtls, String userId) {
        if (dumpDtls == null || dumpDtls.size() == 0){
            return ResponseResult.error("请求参数错误");
        }
        String whsDumpUuid = dumpDtls.get(0).getWhsDumpUuid();
        OverseaWhsDump overseaWhsDump = getOverseaWhsDump(whsDumpUuid);
        if (overseaWhsDump == null){
            return ResponseResult.error("请求转储任务不存在");
        }
        Integer maxItemNumber = this.baseMapper.getWhsDumpMaxItemNumber(whsDumpUuid);
        for (int i = 0; i < dumpDtls.size(); i ++){
            OverseaWhsDumpDtl overseaWhsDumpDtl = new OverseaWhsDumpDtl();
            OverseaWhsDumpDtl dumpDtl = dumpDtls.get(i);
            overseaWhsDumpDtl.setWhsDumpUuid(dumpDtl.getWhsDumpUuid());
            overseaWhsDumpDtl.setItem((i + 1) * 10 + maxItemNumber);
            overseaWhsDumpDtl.setMaterialNo(dumpDtl.getMaterialNo());
            overseaWhsDumpDtl.setBasicUnit(dumpDtl.getBasicUnit());
            overseaWhsDumpDtl.setUnitSales(dumpDtl.getUnitSales());
            overseaWhsDumpDtl.setApplyQtyBasicUnit(dumpDtl.getApplyQtyBasicUnit() == null ? 0.0 : dumpDtl.getApplyQtyBasicUnit());
            overseaWhsDumpDtl.setApplyQtyUnitSales(dumpDtl.getApplyQtyUnitSales() == null ? 0.0 : dumpDtl.getApplyQtyUnitSales());
            overseaWhsDumpDtl.setApplyRemark(dumpDtl.getApplyRemark());
            overseaWhsDumpDtl.setActualQtyBasicUnit(0.0);
            overseaWhsDumpDtl.setActualQtyUnitSales(0.0);
            iOverseaWhsDumpDtlService.save(overseaWhsDumpDtl);
        }
        iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_UPDATE.getDescZh(), WHS_DUMP_UPDATE.getDescEn(), "");
        return ResponseResult.success().add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid));
    }

    /** 转储任务删除行项目 */
    @Override
    public ResponseResult deleteOverseaWhsDumpDtls(List<OverseaWhsDumpDtl> dumpDtls, String userId) {
        if (dumpDtls == null || dumpDtls.size() == 0){
            return ResponseResult.error("请求参数错误");
        }
        String whsDumpUuid = "";
        for (int i = 0; i < dumpDtls.size(); i ++){
            OverseaWhsDumpDtl dumpDtl = dumpDtls.get(i);
            whsDumpUuid = dumpDtl.getWhsDumpUuid();
            Integer item = dumpDtl.getItem();
            iOverseaWhsDumpDtlService.deleteWhsDumpDtl(whsDumpUuid, item);
        }
        iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_UPDATE.getDescZh(), WHS_DUMP_UPDATE.getDescEn(), "");
        return ResponseResult.success().add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid));
    }

    /** OA 审批通过接口 1498718, S */
    @Override
    public ResponseResult oaApproveWhsDump(String oaBianhao, String oaStatus, String userId) {
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
        if (StringUtils.isEmpty(oaBianhao) || StringUtils.isEmpty(oaStatus)){
            ResponseResult.error("请求参数错误");
        }
        QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("OA_BIANHAO", oaBianhao);
        OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);
        if (overseaWhsDump == null){
            return ResponseResult.error("请求转储任务不存在");
        }
        String whsDumpUuid = overseaWhsDump.getWhsDumpUuid();
        if (!WHS_DUMP_SUBMIT_OA.getCode().equals(overseaWhsDump.getSpmsStatus())){
            return ResponseResult.error("当前状态禁止此操作");
        }
        if (OA_APPROVE.equals(oaStatus)){
            overseaWhsDump.setSpmsStatus(WHS_DUMP_OA_APPROVE.getCode());
            overseaWhsDump.setOaApprovalDate(sdf.format(new Date()));
            this.baseMapper.update(overseaWhsDump, queryWrapper);
            iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_OA_APPROVE.getDescZh(), WHS_DUMP_OA_APPROVE.getDescEn(), "");
            return ResponseResult.success("OA审批通过，SPMS更新状态成功");
        } else {
            overseaWhsDump.setSpmsStatus(WHS_DUMP_OA_REJECT.getCode());
            this.baseMapper.update(overseaWhsDump, queryWrapper);
            iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_OA_REJECT.getDescZh(), WHS_DUMP_OA_REJECT.getDescEn(), "");
            return ResponseResult.success("OA审批不通过，SPMS更新状态成功");
        }
    }

    /** 转储任务更新状态变化控制：1-1(保存), 1-3(提交OA), 4-4(驳回保存), 4-3(驳回重提), 5-6(出库完成) */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult updateWhsDump(OverseaWhsDumpDTO overseaWhsDumpDTO,
                                                     String userId, SpmsUser spmsUser) {
        try {
            ResponseResult checkResult = checkUpdate(overseaWhsDumpDTO);
            if (checkResult.getCode() != SUCCESS){
                return checkResult;
            }
            String whsDumpUuid = overseaWhsDumpDTO.getWhsDumpUuid();
            String spmsStatus = overseaWhsDumpDTO.getSpmsStatus();
            QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
            OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);
            overseaWhsDump.setSpmsStatus(spmsStatus);
            overseaWhsDump.setOaRemark(overseaWhsDumpDTO.getOaRemark());
            overseaWhsDump.setSubmitOaDate(overseaWhsDumpDTO.getSubmitOaDate());
            overseaWhsDump.setDumpOutDate(overseaWhsDumpDTO.getDumpOutDate());
            overseaWhsDump.setDumpOutRemark(overseaWhsDumpDTO.getDumpOutRemark());
            overseaWhsDump.setDeliveryDate(overseaWhsDumpDTO.getDeliveryDate());
            int updateResult = this.baseMapper.update(overseaWhsDump, queryWrapper);
            if (updateResult < 1){
                log.info("=======RuntimeException=========创建转储任务表头错误\n");
                throw new RuntimeException("转储任务表头更新错误");
            }

            List<OverseaWhsDumpDtl> dtlList = overseaWhsDumpDTO.getOverseaWhsDumpDtlList();
            for (int i = 0; i < dtlList.size(); i ++){
                OverseaWhsDumpDtl dtl = dtlList.get(i);
                OverseaWhsDumpDtl overseaWhsDumpDtl = new OverseaWhsDumpDtl();
                overseaWhsDumpDtl.setWhsDumpUuid(whsDumpUuid);
                overseaWhsDumpDtl.setItem(dtl.getItem());
                overseaWhsDumpDtl.setApplyQtyBasicUnit(dtl.getApplyQtyBasicUnit() == null ? 0.0 : dtl.getApplyQtyBasicUnit());
                overseaWhsDumpDtl.setApplyQtyUnitSales(dtl.getApplyQtyUnitSales() == null ? 0.0 : dtl.getApplyQtyUnitSales());
                overseaWhsDumpDtl.setApplyRemark(dtl.getApplyRemark());
                overseaWhsDumpDtl.setActualQtyBasicUnit(dtl.getActualQtyBasicUnit());
                overseaWhsDumpDtl.setActualQtyUnitSales(dtl.getActualQtyUnitSales());
                overseaWhsDumpDtl.setActualStorageInfo(dtl.getActualStorageInfo());
                overseaWhsDumpDtl.setActualRemark(dtl.getActualRemark() == null ? "" : dtl.getActualRemark());
                QueryWrapper<OverseaWhsDumpDtl> dtlQueryWrapper = new QueryWrapper<OverseaWhsDumpDtl>()
                        .eq("WHS_DUMP_UUID", whsDumpUuid).eq("ITEM", dtl.getItem());
                iOverseaWhsDumpDtlService.update(overseaWhsDumpDtl, dtlQueryWrapper);
            }

            if (WHS_DUMP_SAVE.getCode().equals(spmsStatus) || WHS_DUMP_OA_REJECT.getCode().equals(spmsStatus)){
                iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_SAVE.getDescZh(), WHS_DUMP_SAVE.getDescEn(), "");
            } else if (WHS_DUMP_DELIVERY.getCode().equals(spmsStatus)){
                iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_DELIVERY.getDescZh(), WHS_DUMP_DELIVERY.getDescEn(), "");
            }

            /** spmsStatus = 3 时更新转储任务提交OA，返回结果 > 0 表示提交成功的OA单据号 */
            if (WHS_DUMP_SUBMIT_OA.getCode().equals(spmsStatus)){
                int oaBianhao = whsDumpSubmitOa(whsDumpUuid, overseaWhsDumpDTO.getSubmitOaDate(), spmsUser);
                OverseaWhsDump whsDump = getOverseaWhsDump(whsDumpUuid);
                if (oaBianhao > 0){
                    //iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_SUBMIT_OA.getDescZh(), WHS_DUMP_SUBMIT_OA.getDescEn(), "");
                    whsDump.setOaWorkflow("0733");
                    whsDump.setSpmsStatus(WHS_DUMP_SUBMIT_OA.getCode());
                    whsDump.setSubmitOaDate(overseaWhsDumpDTO.getSubmitOaDate());
                    whsDump.setOaBianhao(String.valueOf(oaBianhao));
                    this.baseMapper.update(whsDump, queryWrapper);

                    return ResponseResult.success("转储任务提交OA成功")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid))
                            .add("oaBianhao", oaBianhao);
                } else {
                    //iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_SUBMIT_OA_ERROR.getDescZh(), WHS_DUMP_SUBMIT_OA_ERROR.getDescEn(), "");
                    whsDump.setOaWorkflow("0733");
                    whsDump.setSpmsStatus(WHS_DUMP_SAVE.getCode());
                    whsDump.setSubmitOaDate(overseaWhsDumpDTO.getSubmitOaDate());
                    this.baseMapper.update(whsDump, queryWrapper);
                    return ResponseResult.error("转储任务更新成功，提交OA失败")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid))
                            .add("oaBianhao", oaBianhao);
                }
            } else {
                return ResponseResult.success("转储任务更新成功")
                        .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                        .add("overseaWhsDumpDtls", getWhsDumpDtls(whsDumpUuid));
            }
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("请求执行过程出错请重试").add("error", e.getMessage());
        }
    }

    /** 转储任务更新状态变化控制：1-1(保存), 1-3(提交OA), 4-4(驳回保存), 4-3(驳回重提), 5-6(出库完成) */
    ResponseResult checkUpdate(OverseaWhsDumpDTO overseaWhsDumpDTO){
        if (overseaWhsDumpDTO == null || overseaWhsDumpDTO.getOverseaWhsDumpDtlList() == null){
            return ResponseResult.error("请求参数错误");
        }
        String whsDumpUuid = overseaWhsDumpDTO.getWhsDumpUuid();
        Integer dataVersion = overseaWhsDumpDTO.getDataVersion();
        if (StringUtils.isEmpty(whsDumpUuid)){
            return ResponseResult.error("请求参数错误");
        }
        QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);
        if (overseaWhsDump == null || !dataVersion.equals(overseaWhsDump.getDataVersion())){
            return ResponseResult.error("请求转储任务已更新或不存在");
        }
        String currentStatus = overseaWhsDump.getSpmsStatus();
        String targetStatus = overseaWhsDumpDTO.getSpmsStatus();
        if (!WHS_DUMP_SAVE.getCode().equals(currentStatus) && !WHS_DUMP_OA_REJECT.getCode().equals(currentStatus) &&
                !WHS_DUMP_OA_APPROVE.getCode().equals(currentStatus)){
            return ResponseResult.error("当前任务状态禁止此操作");
        }
        if (!WHS_DUMP_SAVE.getCode().equals(targetStatus) && !WHS_DUMP_SUBMIT_OA.getCode().equals(targetStatus) &&
                !WHS_DUMP_OA_REJECT.getCode().equals(targetStatus) && !WHS_DUMP_DELIVERY.getCode().equals(targetStatus)){
            return ResponseResult.error("任务目标状态禁止此操作");
        }
        return ResponseResult.success();
    }

    /** 提交SAP状态变化控制：6/7-8/7(获取PO), 8/9-10/9(获取DN), 获取到DN扣库存 */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult whsDumpToSap(String whsDumpUuid, String postingDate, Integer dataVersion, String userId) {
        try {
            ResponseResult checkResult = checkToSap(whsDumpUuid, postingDate, dataVersion);
            if (checkResult.getCode() != SUCCESS){
                return checkResult;
            }
            QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
            OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);

            QueryWrapper<OverseaWhsDumpDtl> dtlQueryWrapper =
                    new QueryWrapper<OverseaWhsDumpDtl>().eq("WHS_DUMP_UUID", whsDumpUuid).gt("ACTUAL_QTY_BASIC_UNIT", 0);
            //List<OverseaWhsDumpDtl> dumpDtlList = iOverseaWhsDumpDtlService.list(dtlQueryWrapper);

            String spmsStatus = overseaWhsDump.getSpmsStatus();
            /** 第一次提交 SAP 获取 PO；状态变化控制：6/7-8/7(获取PO)；*/
            JSONObject dataToSap = new JSONObject();
            if (WHS_DUMP_DELIVERY.getCode().equals(spmsStatus) || WHS_DUMP_PO_ERROR.getCode().equals(spmsStatus)){
                dataToSap = iFormatDataToSapService.formatDataToSap(
                        this.baseMapper.getSapPoHead(whsDumpUuid), this.baseMapper.getSapPoItem(whsDumpUuid), "Z_POS_PO_CREATE", "ZZD");
                log.info("=======dataToSap get PO=========\n" + dataToSap);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                log.info("=======message get PO=========\n" + message);

                if (!SAP_SUCCESS.equals(message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("TYPE"))){
                    overseaWhsDump.setSpmsStatus(WHS_DUMP_PO_ERROR.getCode());
                    overseaWhsDump.setPurchasePostingDate(postingDate);
                    this.baseMapper.update(overseaWhsDump, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_PO_ERROR.getDescZh(),
                    WHS_DUMP_PO_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务提交SAP获取PO");
                    return ResponseResult.error("转储任务提交SAP获取PO失败")
                         .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                         .add("sapReturnedData", message)
                         .add("dataToSap", dataToSap);
                }
                String sapMsg = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("MESSAGE");
                String sapPurchaseNo = sapMsg.substring(sapMsg.length() - 10);
                overseaWhsDump.setSpmsStatus(WHS_DUMP_PO.getCode());
                overseaWhsDump.setPurchasePostingDate(postingDate);
                overseaWhsDump.setSapPurchaseNo(sapPurchaseNo);

                this.baseMapper.update(overseaWhsDump, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_PO.getDescZh() + ":" + sapPurchaseNo,
                WHS_DUMP_PO.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务提交SAP获取PO");
                return ResponseResult.success("转储任务提交SAP获取PO成功")
                        .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                        .add("sapReturnedMessage", message)
                        .add("dataToSap", dataToSap);
            } else {
                /** 第二次提交 SAP 获取 DN；状态变化控制：8/9-10/9(获取DN)；*/
                dataToSap = whsDumpToSapGetDn(overseaWhsDump, postingDate);
                log.info("=======dataToSap get DN=========\n" + dataToSap);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                log.info("=======message get DN=========\n" + message);

                if (!SAP_SUCCESS.equals(message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_TYPE"))){
                    overseaWhsDump.setSpmsStatus(WHS_DUMP_DN_ERROR.getCode());
                    overseaWhsDump.setPostingDate(postingDate);
                    this.baseMapper.update(overseaWhsDump, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_DN_ERROR.getDescZh(),
                    WHS_DUMP_DN_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务提交SAP获取DN");
                    return ResponseResult.error("转储任务提交SAP获取DN失败")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("sapReturnedData", message)
                            .add("dataToSap", dataToSap);
                }
                String sapDeliveryNote = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_VBELN");
                String sapVoucherYear = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MJAHR");
                overseaWhsDump.setSpmsStatus(WHS_DUMP_DN.getCode());
                overseaWhsDump.setSapDeliveryNote(sapDeliveryNote);
                overseaWhsDump.setPostingDate(postingDate);
                overseaWhsDump.setSapVoucherYear(sapVoucherYear);
                this.baseMapper.update(overseaWhsDump, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_DN.getDescZh() + ":" + sapDeliveryNote,
                WHS_DUMP_DN.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务提交SAP获取DN");

                String werks = overseaWhsDump.getWerksDumpOut();
                String whsLocationCode = overseaWhsDump.getWhsLocationCodeDumpOut();

                ResponseResult updateInventoryResult = updateOverseaWhsDumpInventory(whsDumpUuid, SUB, userId, "16", werks, whsLocationCode, overseaWhsDump.getMovementType(), "转储出库");
                if (updateInventoryResult.getCode() != SUCCESS){
                    log.info("=======RuntimeException=========\n" + updateInventoryResult.getMsg());
                    throw new RuntimeException("储位库存更新错误\n" + updateInventoryResult.getMsg());
                }

                iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_INV_UPDATE.getDescZh(), WHS_DUMP_INV_UPDATE.getDescEn(), "");

                return ResponseResult.success("转储任务提交SAP获取DN成功")
                        .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                        .add("sapReturnedMessage", message)
                        .add("dataToSap", dataToSap);
            }
        }catch (FeignException feignException){
            feignException.printStackTrace();
            return ResponseResult.error("请求SAP失败 FeignException").add("error", feignException.getMessage());
        }
        catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("请求执行过程出错请重试").add("error", e.getMessage());
        }
    }

    ResponseResult updateOverseaWhsDumpInventory(String whsDumpUuid, String operateType, String userId, String logType, String werks, String whsLocationCode, String movementType, String remark){
        QueryWrapper<OverseaWhsDumpDtl> dtlQueryWrapper =
                new QueryWrapper<OverseaWhsDumpDtl>().eq("WHS_DUMP_UUID", whsDumpUuid).gt("ACTUAL_QTY_BASIC_UNIT", 0);
        List<OverseaWhsDumpDtl> dumpDtlList = iOverseaWhsDumpDtlService.list(dtlQueryWrapper);
        if (dumpDtlList == null || dumpDtlList.size() == 0){
            return ResponseResult.error("出库任务明细数据查询不存在");
        }
        for (OverseaWhsDumpDtl whsDumpDtl : dumpDtlList){
            String materialNo = whsDumpDtl.getMaterialNo();
            double actualQtyBasicUnit = whsDumpDtl.getActualQtyBasicUnit();
            if (actualQtyBasicUnit > 0){
                //storageInfoArray 结构参考：[{"storageUuid":"f17e13b4d9ad4d39ba55548eff544391","qty":100,"storageNo":"C010101"}]
                JSONArray storageInfoArray = JSONArray.parseArray(whsDumpDtl.getActualStorageInfo());
                for (int i = 0; i < storageInfoArray.size(); i ++){
                    JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
                    String storageUuid = storageInfoObj.getString("storageUuid");
                    double qty = storageInfoObj.getDoubleValue("qty");
                    if (qty > 0){
                        ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuid, materialNo, qty, operateType);
                        if (updateInventory.getCode() != SUCCESS){
                            return updateInventory;
                        }
                        String comments = operateType.equals(ADD) ? WHS_DUMP_ADD : WHS_DUMP_SUB;
                        iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, logType, whsDumpUuid, comments, userId, remark, werks, whsLocationCode, movementType);
                    }
                }
            }
        }
        return ResponseResult.success();
    }

    /** 提交SAP状态变化控制：6/7-8/7(获取PO), 8/9-10/9(获取DN), 获取到DN扣库存 */
    ResponseResult checkToSap(String whsDumpUuid, String postingDate, Integer dataVersion){
        if (StringUtils.isEmpty(whsDumpUuid) || StringUtils.isEmpty(postingDate) || INVALID_DATE.equals(postingDate) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);

        QueryWrapper<OverseaWhsDumpDtl> dtlQueryWrapper =
                new QueryWrapper<OverseaWhsDumpDtl>().eq("WHS_DUMP_UUID", whsDumpUuid).gt("ACTUAL_QTY_BASIC_UNIT", 0);
        List<OverseaWhsDumpDtl> dumpDtlList = iOverseaWhsDumpDtlService.list(dtlQueryWrapper);

        if (overseaWhsDump == null || !dataVersion.equals(overseaWhsDump.getDataVersion())){
            return ResponseResult.error("请求转储任务已更新或不存在");
        }
        if (dumpDtlList == null || dumpDtlList.size() == 0){
            return ResponseResult.error("请求转储任务明细有效行数据为空");
        }
        String spmsStatus = overseaWhsDump.getSpmsStatus();
        if (WHS_DUMP_DELIVERY.getCode().equals(spmsStatus) || WHS_DUMP_PO_ERROR.getCode().equals(spmsStatus)){

        } else if(WHS_DUMP_PO.getCode().equals(spmsStatus) || WHS_DUMP_DN_ERROR.getCode().equals(spmsStatus)){
            if (StringUtils.isEmpty(overseaWhsDump.getSapPurchaseNo())){
                return ResponseResult.error("采购订单号不能为空");
            }
            ResponseResult checkInventoryResult = checkMaterialInventory(dumpDtlList);
            if (checkInventoryResult.getCode() != SUCCESS){
                return checkInventoryResult;
            }
        } else {
            return ResponseResult.error("请求任务当前状态禁止此操作");
        }
        return ResponseResult.success();
    }

    /** 扣减库存时，检查任务明细行数据每一行物料库存是否足够扣减 */
    ResponseResult checkMaterialInventory(List<OverseaWhsDumpDtl> dumpDtlList){
        for (OverseaWhsDumpDtl dtl : dumpDtlList){
            Integer item = dtl.getItem();
            String materialNo = dtl.getMaterialNo();
            String storageInfo = dtl.getActualStorageInfo();
            if (StringUtils.isEmpty(storageInfo)){
                return ResponseResult.error("实收数量大于0的行:" + item + "，料号:" + materialNo + "储位信息无效");
            }
            JSONArray storageInfoArray = JSONArray.parseArray(storageInfo);
            for (int i = 0; i < storageInfoArray.size(); i ++){
                JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
                String storageUuid = storageInfoObj.getString("storageUuid");
                double qty = storageInfoObj.getDoubleValue("qty");
                String storageNo = storageInfoObj.getString("storageNo");
                if (qty > 0){
                    WhsStorageInventory whsStorageInventory = iWhsStorageInventoryService.getWhsStorageInventory(storageUuid, materialNo);
                    if (whsStorageInventory == null){
                        return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "无可用库存");
                    }
                    if (qty > whsStorageInventory.getAvailableQty()){
                        return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "可用库存不足");
                    }
                }
            }
        }
        return ResponseResult.success();
    }

    /** 获取DN请求SAP结构拼接 */
    JSONObject whsDumpToSapGetDn(OverseaWhsDump overseaWhsDump, String postingDate){
        JSONObject doc = new JSONObject();
        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        JSONObject Head = new JSONObject();
        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());

        Head.put("iFlag", "01");
        Head.put("iBudat", postingDate.replaceAll("-", ""));
        Head.put("iEbeln", StringUtils.isEmpty(overseaWhsDump.getSapPurchaseNo()) ? "" : overseaWhsDump.getSapPurchaseNo());
        Head.put("iVbeln", StringUtils.isEmpty(overseaWhsDump.getSapDeliveryNote()) ? "" : overseaWhsDump.getSapDeliveryNote());
        Head.put("iLgort", StringUtils.isEmpty(overseaWhsDump.getWhsLocationCodeDumpOut()) ? "" : overseaWhsDump.getWhsLocationCodeDumpOut());

        REQUEST_DATA.put("Head", Head);
        REQUEST_DATA.put("Operation", "Z_SPMS_DN_POST");
        REQUEST_DATA.put("Type", "DN_POST");
        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);
        doc.put("REQUEST", REQUEST);
        return doc;
    }

    /**
     海外SPMS转储单据状态:
         0删除；1草稿；2待审批；3SPMS审批通过(提交OA);4OA驳回(操作同1);5OA审批通过(出库中);6出库完成;7提交SAP获取PO失败;
         8提交SAP获取PO;9提交SAP获取DN失败;10提交SAP获取DN成功(扣转出方库存);11转出已撤销(撤到状态5出库中，SAP撤回成功则加回库存);
     转储任务撤回状态变化及处理：
         2-1 更新状态; 5-1 更新状态;
         6-5 更新状态; 7-5 更新状态;
         8-5 从SAP撤回PO; 9-5 从SAP撤回PO;
         10-8,8-5 从SAP撤回DN、加回库存、从SAP撤回PO;
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult cancelWhsDump(String whsDumpUuid, String cancelPostingDate, Integer dataVersion, String userId) {
        try {
            ResponseResult checkCancelResult = checkCancel(whsDumpUuid, cancelPostingDate, dataVersion);
            if (checkCancelResult.getCode() != SUCCESS){
                return checkCancelResult;
            }
            QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
            OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);
            String spmsStatus = overseaWhsDump.getSpmsStatus();
            String whsLocationCodeDumpOut = overseaWhsDump.getWhsLocationCodeDumpOut();
            if (WHS_DUMP_PENDING.getCode().equals(spmsStatus) || WHS_DUMP_OA_APPROVE.getCode().equals(spmsStatus)){
                overseaWhsDump.setSpmsStatus(WHS_DUMP_SAVE.getCode());
                this.baseMapper.update(overseaWhsDump, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_CANCEL_TO1.getDescZh(), WHS_DUMP_CANCEL_TO1.getDescEn(), "");
                return ResponseResult.success("撤回成功").add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid));
            }
            if (WHS_DUMP_DELIVERY.getCode().equals(spmsStatus) || WHS_DUMP_PO_ERROR.getCode().equals(spmsStatus)){
                overseaWhsDump.setSpmsStatus(WHS_DUMP_OA_APPROVE.getCode());
                this.baseMapper.update(overseaWhsDump, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_CANCEL_TO5.getDescZh(), WHS_DUMP_CANCEL_TO5.getDescEn(), "");
                return ResponseResult.success("撤回成功").add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid));
            }
            if (WHS_DUMP_PO.getCode().equals(spmsStatus)
                    || WHS_DUMP_DN_ERROR.getCode().equals(spmsStatus)){
                String po = overseaWhsDump.getSapPurchaseNo();
                Map<String, Object> Head = new HashMap<>();
                Head.put("PO_NUMBER", po);
                Head.put("ZDEL", "X");
                JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(
                        Head, this.baseMapper.sapPoCancelItem(whsDumpUuid), "Z_POS_PO_CREATE", "ZZD_ITEM_OFF");
                log.info("=======dataToSap cancel PO=========\n" + dataToSap);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                log.info("=======message cancel PO=========\n" + message);

                if (!SAP_SUCCESS.equals(message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("TYPE"))){
                    iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_CANCEL_ERROR.getDescZh(),
                            WHS_DUMP_CANCEL_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务撤销PO提交SAP");
                    return ResponseResult.error("转储任务撤销PO提交SAP失败")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("sapReturnedData", message)
                            .add("dataToSap", dataToSap);
                } else {
                    overseaWhsDump.setSpmsStatus(WHS_DUMP_OA_APPROVE.getCode());
                    this.baseMapper.update(overseaWhsDump, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_CANCEL_TO5.getDescZh(),
                            WHS_DUMP_CANCEL_TO5.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务撤销PO提交SAP");
                    return ResponseResult.success("转储任务撤销PO提交SAP成功")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("sapReturnedData", message)
                            .add("dataToSap", dataToSap);
                }
            }


            if (WHS_DUMP_DN.getCode().equals(spmsStatus)){
                String po = overseaWhsDump.getSapPurchaseNo();
                String dn = overseaWhsDump.getSapDeliveryNote();
                JSONObject dataToSap = dataToSapCancel(cancelPostingDate, po, dn, whsLocationCodeDumpOut);
                log.info("=======dataToSap Cancel PO/DN=========\n" + dataToSap);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                log.info("=======message Cancel PO/DN=========\n" + message);
                if (!SAP_SUCCESS.equals(message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_TYPE"))){
                    iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_CANCEL_ERROR.getDescZh(),
                            WHS_DUMP_CANCEL_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务撤销DN提交SAP");
                    return ResponseResult.error("转储任务撤销DN提交SAP失败")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("sapReturnedData", message)
                            .add("dataToSap", dataToSap);
                } else {
                    overseaWhsDump.setSpmsStatus(WHS_DUMP_PO.getCode());
                    overseaWhsDump.setCancelVoucherNumber(message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MBLNR"));
                    overseaWhsDump.setCancelPostingDate(cancelPostingDate);
                    overseaWhsDump.setCancelVoucherYear(message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MJAHR"));
                    this.baseMapper.update(overseaWhsDump, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_CANCEL_TO5.getDescZh(),
                            WHS_DUMP_CANCEL_TO5.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "转储任务撤销DN提交SAP");

                    if (WHS_DUMP_DN.getCode().equals(spmsStatus)){
                        String werks = overseaWhsDump.getWerksDumpOut();
                        String whsLocationCode = overseaWhsDump.getWhsLocationCodeDumpOut();
                        ResponseResult cancelAddWhs = updateOverseaWhsDumpInventory(whsDumpUuid, ADD, userId, "19",
                                werks, whsLocationCode, overseaWhsDump.getMovementType(), "转储撤销入库");

                        if (cancelAddWhs.getCode() != SUCCESS){
                            log.info("=======RuntimeException=========\n" + cancelAddWhs.getMsg());
                            throw new RuntimeException("储位库存更新错误\n" + cancelAddWhs.getMsg());
                        }

                        iOverseaOperateLogService.addOverseaOperateLog(userId, whsDumpUuid, WHS_DUMP_INV_UPDATE.getDescZh(), WHS_DUMP_INV_UPDATE.getDescEn(), "");
                    }

                    return ResponseResult.success("转储任务撤销DN提交SAP成功")
                            .add("overseaWhsDump", getOverseaWhsDump(whsDumpUuid))
                            .add("sapReturnedData", message)
                            .add("dataToSap", dataToSap);
                }
            }
            return ResponseResult.error("请求错误");
        }catch (FeignException feignException){
            feignException.printStackTrace();
            return ResponseResult.error("请求SAP失败 FeignException").add("error", feignException.getMessage());
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("转储撤销更新单据或提交SAP失败 Exception").add("error", e.getMessage());
        }
    }

    /**
     海外SPMS转储单据状态:
     0删除；1草稿；2待审批；3SPMS审批通过(提交OA);4OA驳回(操作同1);5OA审批通过(出库中);6出库完成;7提交SAP获取PO失败;
     8提交SAP获取PO;9提交SAP获取DN失败;10提交SAP获取DN成功(扣转出方库存);11转出已撤销(撤到状态5出库中，SAP撤回成功则加回库存);
     转储任务撤回状态变化及处理：
     2-1 更新状态; 5-1 更新状态;
     6-5 更新状态; 7-5 更新状态;
     8-5 从SAP撤回PO; 9-5 从SAP撤回PO;
     10-8,8-5 从SAP撤回DN、加回库存、从SAP撤回PO;
     */
    ResponseResult checkCancel(String whsDumpUuid, String cancelPostingDate, Integer dataVersion){
        if (StringUtils.isEmpty(whsDumpUuid) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        QueryWrapper<OverseaWhsDump> queryWrapper = new QueryWrapper<OverseaWhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        OverseaWhsDump overseaWhsDump = this.baseMapper.selectOne(queryWrapper);
        if (overseaWhsDump == null || !dataVersion.equals(overseaWhsDump.getDataVersion())){
            return ResponseResult.error("请求转储任务已更新或不存在");
        }
        String spmsStatus = overseaWhsDump.getSpmsStatus();
        if (WHS_DUMP_PENDING.getCode().equals(spmsStatus) || WHS_DUMP_OA_APPROVE.getCode().equals(spmsStatus)){

        } else if (WHS_DUMP_DELIVERY.getCode().equals(spmsStatus) || WHS_DUMP_PO_ERROR.getCode().equals(spmsStatus)){

        } else if (WHS_DUMP_PO.getCode().equals(spmsStatus) || WHS_DUMP_DN_ERROR.getCode().equals(spmsStatus)){
            if (StringUtils.isEmpty(cancelPostingDate) || INVALID_DATE.equals(cancelPostingDate)){
                return ResponseResult.error("撤销过账日期不能为空");
            }
            String po = overseaWhsDump.getSapPurchaseNo();
            if (StringUtils.isEmpty(po)){
                return ResponseResult.error("单据采购订单号PO为空，禁止撤销操作");
            }
        } else if (WHS_DUMP_DN.getCode().equals(spmsStatus)){
            if (StringUtils.isEmpty(cancelPostingDate) || INVALID_DATE.equals(cancelPostingDate)){
                return ResponseResult.error("撤销过账日期不能为空");
            }
            String dn = overseaWhsDump.getSapDeliveryNote();
            if (StringUtils.isEmpty(dn)){
                return ResponseResult.error("单据交货单号DN为空，禁止撤销操作");
            }
        } else {
            return ResponseResult.error("当前转储任务状态不可撤销");
        }
        return ResponseResult.success();
    }

    JSONObject dataToSapCancel(String cancelPostingDate, String sapPurchaseOrder, String sapDeliveryNote, String whsLocationCodeDumpOut){
        JSONObject obj = new JSONObject();

        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        JSONObject Head = new JSONObject();

        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());

        Head.put("iFlag", "02");
        Head.put("iBudat", cancelPostingDate.replaceAll("-", ""));
        //Head.put("iEbeln", StringUtils.isEmpty(sapPurchaseOrder) ? "" : sapPurchaseOrder);
        Head.put("iEbeln", "");
        Head.put("iVbeln", StringUtils.isEmpty(sapDeliveryNote) ? "" : sapDeliveryNote);
        Head.put("iLgort", StringUtils.isEmpty(whsLocationCodeDumpOut) ? "" : whsLocationCodeDumpOut);

        REQUEST_DATA.put("Head", Head);
        REQUEST_DATA.put("Operation", "Z_SPMS_DN_POST");
        REQUEST_DATA.put("Type", "DN_POST");

        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);
        obj.put("REQUEST", REQUEST);
        return obj;
    }
}
